package com.yinhai.ta404.component.org.sysmg.resource.rest;

import com.alibaba.fastjson.JSON;
import com.yinhai.ta404.component.org.core.autoconfigure.TaRootConfig;
import com.yinhai.ta404.component.org.core.constant.OrgConstant;
import com.yinhai.ta404.component.org.core.vo.TaResourceVo;
import com.yinhai.ta404.component.org.sysmg.resource.entity.TaPageElementPo;
import com.yinhai.ta404.component.org.sysmg.resource.entity.TaResourcePo;
import com.yinhai.ta404.component.org.sysmg.resource.properties.PortalProperties;
import com.yinhai.ta404.component.org.sysmg.resource.service.read.PageElementReadService;
import com.yinhai.ta404.component.org.sysmg.resource.service.read.ResourceReadService;
import com.yinhai.ta404.component.org.sysmg.resource.service.write.impl.ResourceWriteServiceImpl;
import com.yinhai.ta404.component.org.sysmg.system.entity.TaAccessSystemPo;
import com.yinhai.ta404.component.org.sysmg.system.service.read.AccessSystemReadService;
import com.yinhai.ta404.core.restservice.BaseRestService;
import com.yinhai.ta404.core.restservice.annotation.RestService;
import com.yinhai.ta404.core.utils.ValidateUtil;
import com.yinhai.ta404.core.validate.annotation.V;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


@Validated
@RestService("menu/menuAction")
public class ResourceRestService extends BaseRestService {

    @Resource
    ResourceReadService resourceReadService;

    @Resource
    PageElementReadService pageElementReadService;

    @Autowired
    TaRootConfig rootConfig;

    @Autowired
    AccessSystemReadService accessSystemReadService;

    @Autowired
    PortalProperties portalProperties;

    private final static Logger logger = LoggerFactory.getLogger(ResourceRestService.class);

    @RequestMapping("queryRootChildrenMenus")
    public void getResourceFromRoot() {
        if(null != getCurUserAccount())
            logger.info("queryRootChildrenMenus start"+ JSON.toJSONString(getCurUserAccount()));
        else
            logger.info("queryRootChildrenMenus start null");

        List<TaResourceVo> taResourceVoList = resourceReadService.queryResourceByUserId(getCurUserAccount());
        taResourceVoList = taResourceVoList.stream()
                .filter(vo -> !rootConfig.getWorkbenchParentId().equals(vo.getResourceId()) && OrgConstant.NO.equals(vo.getWorkbench()) && (OrgConstant.YES.equals(vo.getDisplay()) || ValidateUtil.isEmpty(vo.getDisplay())))
                .collect(Collectors.toList());
        logger.info("queryRootChildrenMenus start1");
        Map<String, String> sysInfo;
        if(portalProperties.getEnable()){

            logger.info("queryRootChildrenMenus start2");
           sysInfo = loadSysInfo();
        }else{

            logger.info("queryRootChildrenMenus start3");
            sysInfo = new HashMap<>(4);
            if(ValidateUtil.isEmpty(portalProperties.getLoadOtherSys())){
                logger.info("queryRootChildrenMenus start4");
                taResourceVoList = taResourceVoList.stream().filter(vo -> portalProperties.getSysCode().equals(vo.getSysCode())).collect(Collectors.toList());
            }else if(!portalProperties.getLoadOtherSys().contains(PortalProperties.LOAD_ALL_SYSTEM)){
                logger.info("queryRootChildrenMenus start5");
                taResourceVoList = taResourceVoList.stream().filter(vo -> portalProperties.getLoadOtherSys().contains(vo.getSysCode()) || portalProperties.getSysCode().equalsIgnoreCase(vo.getSysCode())).collect(Collectors.toList());
            }
        }

        logger.info("queryRootChildrenMenus start6");

        List<Map<String, Object>> mapList = new ArrayList<>();
        taResourceVoList.forEach(resourceVo -> {
            Map<String, Object> map = new HashMap<>(16);
            map.put("id", resourceVo.getResourceId());
            map.put("name", resourceVo.getName());
            map.put("url", resourceVo.getUrl());
            map.put("prefix", sysInfo.get(resourceVo.getSysCode()));
            map.put("iconColor", resourceVo.getIconColor());
            map.put("icon", resourceVo.getIcon());
            map.put("pid", resourceVo.getpResourceId());
            map.put("orderNo", resourceVo.getOrderNo());
            mapList.add(map);
        });
        logger.info("queryRootChildrenMenus start7");
        setData("menus", resourceReadService.generateResourceTree(mapList, "id", "pid", OrgConstant.CHILDREN));
        logger.info("queryRootChildrenMenus end");
    }

    private Map<String, String> loadSysInfo() {
        List<TaAccessSystemPo> pos = accessSystemReadService.queryEffectiveAccess();
        if (ValidateUtil.isEmpty(pos)) {
            return new HashMap<>(0);
        }

        pos = pos.stream().filter( po -> !portalProperties.getSysCode().equalsIgnoreCase(po.getSysCode())).collect(Collectors.toList());
        Map<String, String> resultMap = new HashMap<>(16);
        pos.forEach(po -> {
            String address;
            String domain = po.getDomain();
            if (null == domain) {
                domain = "unknown";
            }
            String protocol = po.getProtocol();
            String contextPath = po.getContextPath();
            String context = contextPath.startsWith(OrgConstant.PATH_SEPARATOR) ? contextPath : OrgConstant.PATH_SEPARATOR + contextPath;
            address = protocol + "://" + domain + ":" + po.getPort() + context + OrgConstant.PATH_SEPARATOR;
            resultMap.put(po.getSysCode(), address);
        });
        return resultMap;
    }


    @RequestMapping("queryElementByResourceId")
    public void queryElementByResourceId(@V({"notnull"}) String resourceId) {
        setData("elementList", getMapList(resourceReadService.queryResource(resourceId)));
    }

    @RequestMapping("querySameLevelElementByResourceId")
    public void querySameElementByResourceId(@V({"notnull"}) String resourceId) {
        TaResourceVo resourceVo = resourceReadService.queryResource(resourceId);
        List<TaResourceVo> resourceVoList = resourceReadService.queryNextLevelResourceWithSelf(resourceVo.getpResourceId());


        setData("list", resourceVoList.stream().filter(vo -> !resourceVo.getpResourceId().equals(vo.getResourceId())).
                map(this::getMapList).collect(Collectors.toList()));
    }


    @RequestMapping("queryAllElement")
    public void queryAllEffectiveElement() {
        List<TaResourcePo> resourcePos = resourceReadService.queryByUserIdWithField01(getCurUserId(), null);
        if (ValidateUtil.isEmpty(resourcePos)) {
            return;
        }
        Set<String> idSet = resourcePos.stream().map(TaResourcePo::getResourceId).collect(Collectors.toSet());
        List<TaResourcePo> btnPos = resourceReadService.queryBtn(ResourceWriteServiceImpl.BUTTON_TYPE);

        Map<String, List<TaResourcePo>> map = new HashMap<>(32);
        if(btnPos == null || btnPos.isEmpty()){
            setData("list", new ArrayList<>());
            return;
        }
        btnPos.forEach(po -> {
            String presourceId = po.getpResourceId();
            List<TaResourcePo> list = map.computeIfAbsent(presourceId, k -> new ArrayList<>());
            list.add(po);
            map.put(presourceId, list);
        });
        List<Map<String, Object>> mapList = new ArrayList<>();
        map.forEach((k,v) -> {
            if(idSet.contains(k)) {
                Map<String, Object> resultMap = new HashMap<>(8);
                resultMap.put("resourceId", k);
                resultMap.put("authority", OrgConstant.RESOURCE_UI_AUTHORITYPOLICY_ALONE);
                resultMap.put("defaultAuth", OrgConstant.ELEMENT_AUTHORITY_POLICY_DISPLAY_EDIT);
                resultMap.put("list", v.stream().map(po -> {
                    Map<String, Object> elementMap = new HashMap<>(32);
                    elementMap.put("id", po.getUrl());
                    elementMap.put("authority", idSet.contains(po.getResourceId()) ? OrgConstant.ELEMENT_AUTHORITY_POLICY_DISPLAY_EDIT : OrgConstant.ELEMENT_AUTHORITY_POLICY_HIDDEN);
                    elementMap.put("uuid", po.getResourceId());
                    return elementMap;
                }).collect(Collectors.toList()));
                mapList.add(resultMap);
            }
        });
       setData("list", mapList);
    }

    private Map<String, Object> getMapList(TaResourceVo vo) {
        Map<String, Object> map = new HashMap<>(4);
        map.put("resourceId", vo.getResourceId());
        map.put("authority", vo.getUiAuthorityPolicy());
        List<Map<String, Object>> list = new ArrayList<>(0);
        if (OrgConstant.RESOURCE_UI_AUTHORITYPOLICY_ALONE.equals(vo.getUiAuthorityPolicy())) {
            list = pageElementReadService.queryEffectiveByResourceId(vo.getResourceId()).stream().map(element -> {
                Map<String, Object> elementMap = new HashMap<>(16);
                elementMap.put("id", element.getElementId());
                elementMap.put("authority", element.getAuthorityPolicy());
                elementMap.put("uuid", element.getPageElementId());
                return elementMap;
            }).collect(Collectors.toList());
        }
        map.put("list", list);
        return map;
    }

    @RequestMapping("queryMenuByMenuId")
    public void queryMenuByMenuId(@V({"notnull"}) String modulePartId) {
        Map<String,String> menuMap = new HashMap();
        TaResourcePo taResourcePo = resourceReadService.queryMenuByMenuId(modulePartId);
        menuMap.put("MENUURL",taResourcePo.getUrl());
        menuMap.put("MENUNAME",taResourcePo.getName());

        setData("menuMap", menuMap);
    }

}
